package org.zjx.command.composite;

import com.alibaba.fastjson2.JSON;
import lombok.Getter;
import lombok.SneakyThrows;
import org.zjx.command.Command;
import org.zjx.identify.FontUtil;
import org.zjx.command.service.IdentifyErrorCommand;
import org.zjx.core.IWindow;
import org.zjx.entity.Font;
import org.zjx.entity.ParagraphBean;
import org.zjx.enums.FontAttribute;
import org.zjx.state.StateManager;
import org.zjx.util.ImageUtil;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Getter
public class IdentifyFontCommand extends Command {
    private static final String identifyResultTag = "identifyResult";
    public static Map<FontAttribute, List<Font>> fontMap = new HashMap<>();

    private final BufferedImage image;
    private final Rectangle rectangle;
    private final List<Color> colors;
    private final FontAttribute fontAttribute;
    private final int fontHeight;
    private List<ParagraphBean.Word> result;

    public IdentifyFontCommand(IWindow targetWindow, StateManager stateManager, BufferedImage image, Rectangle rectangle, List<Color> colors, FontAttribute fontAttribute, int fontHeight) {
        super(targetWindow, false, stateManager);
        this.image = image;
        this.rectangle = rectangle;
        this.colors = colors;
        this.fontHeight = fontHeight;
        this.fontAttribute = fontAttribute;
    }

    @Override
    protected void doExecute() throws Exception {
        if (image == null) throw new IllegalArgumentException("image is null");
        List<Font> fonts = getFontAttributes(fontAttribute);
        if (rectangle == null) {
            result = identify(image, colors, fonts, fontHeight);
        } else {
            BufferedImage bufferedImage = ImageUtil.cutImage(image, rectangle);
            List<ParagraphBean.Word> words = identify(bufferedImage, colors, fonts, fontHeight);
            for (ParagraphBean.Word word : words) {
                Rectangle wordRectangle = word.getRectangle();
                wordRectangle.x = wordRectangle.x + rectangle.x;
                wordRectangle.y = wordRectangle.y + rectangle.y;
            }
            this.result = words;
        }
        System.out.println("识别结果:" + result);
    }

    public static Rectangle getTextRectangle(List<ParagraphBean.Word> result,String text ) {
        if (result == null) return null;
        for (ParagraphBean.Word word : result) {
            if (word.getName().contains(text)) return word.getRectangle();
        }
        return null;
    }

    public static String identifyString(List<ParagraphBean.Word> result) {
        if (result == null) return "";
        StringBuilder sb = new StringBuilder();
        for (ParagraphBean.Word word : result) {
            if (word.getName().contains("null")) word.setName(word.getName().replace("null", ""));
            sb.append(word.getName());
        }
        return sb.toString();
    }

    public List<ParagraphBean.Word> identify(BufferedImage image, List<Color> colors, List<Font> fonts, int fontHeight) {
        ParagraphBean paragraphBean = new ParagraphBean();
        paragraphBean.add(FontUtil.categories(identifyResultTag, colors, image, fonts, fontHeight));
        if (paragraphBean.getChildren() == null || paragraphBean.getChildren().isEmpty()) return null;
        List<ParagraphBean.Word> words = paragraphBean.getChildren().get(0).getWords();
        if (words == null || words.isEmpty()) return null;
        for (ParagraphBean.Word word : words) {
            if (word.getName().contains("null")) {
                //记录错误/未记录字库 图片
                IdentifyErrorCommand identifyErrorCommand = new IdentifyErrorCommand(targetWindow, stateManager, image, rectangle, fontAttribute);
                targetWindow.submitCommand(identifyErrorCommand);
                word.setName(word.getName().replace("null", ""));
                break;
            }
        }
        return words;
    }

    @SneakyThrows
    public List<Font> getFontAttributes(FontAttribute fontAttribute) {
        if (fontMap.containsKey(fontAttribute)) {
            return fontMap.get(fontAttribute);
        }
        String filePath = "fonts/" + fontAttribute.getName() + ".json";
        String json = readFileAsString(Paths.get(filePath));
        List<Font> fonts = JSON.parseArray(json, Font.class);
        if (!fonts.isEmpty()) fontMap.put(fontAttribute, fonts);
        return fonts;
    }

    /**
     * 高效、健壮的文件读取方法（兼容 Java 8）
     */
    private String readFileAsString(Path path) throws IOException {
        // 检查文件是否存在
        if (!Files.exists(path)) {
            throw new FileNotFoundException("文件不存在: " + path);
        }

        // 检查是否为文件
        if (!Files.isRegularFile(path)) {
            throw new IOException("路径不是文件: " + path);
        }

        // 估计文件大小
        long fileSize = Files.size(path);
        int initialCapacity = (fileSize > 0 && fileSize < Integer.MAX_VALUE) ?
                (int) fileSize : 16384; // 16KB 默认

        try (
                InputStream inputStream = Files.newInputStream(path);
                Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
            StringBuilder content = new StringBuilder(initialCapacity);
            char[] buffer = new char[16384]; // 16KB 缓冲区
            int charsRead;

            while ((charsRead = reader.read(buffer)) != -1) {
                content.append(buffer, 0, charsRead);
            }

            return content.toString();
        } catch (IOException e) {
            throw new IOException("读取文件失败: " + path, e);
        }
    }
}
